package pl.umk.mat.fred.unicore.urc.storagemanagement.views;

import java.util.ListIterator;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import pl.umk.mat.fred.unicore.urc.storagemanagement.StorageManagementActivator;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.ChangePermissionsAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.CopyAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.CreateNewCatalogAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.CreateNewFileAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.DeleteAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.DoubleClickAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.DownloadRemoteFilesAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.FindAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.HideShowStoragesAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.PasteAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.RenameAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.SendLocalFilesAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.findNavigation.CloseNaviBarAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.findNavigation.NextSearchResultAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.findNavigation.PrevSearchResultAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.listeners.MenuListener;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.ContentProviderImplementation;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.LabelProviderImplementation;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.filters.AccessDeniedFilter;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.filters.OtherFileFilter;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.GridNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.RootNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.StorageNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.sorters.LastModifiedSorter;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.sorters.NameSorter;
import pl.umk.mat.fred.unicore.urc.storagemanagement.unicore.Storage;

public class StorageBrowserView extends ViewPart {

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "pl.umk.mat.fred.unicore.urc.storagemanagement.views.StorageManagementView";

	private RootNode rootNode;
	private TreeViewer treeViewer;
	private IStructuredSelection clipboard;
	
	private DoubleClickAction doubleClickAction;
	private HideShowStoragesAction hideShowStoragesAction;
	private RenameAction renameAction;
	private DeleteAction deleteAction; 
	private CreateNewCatalogAction createNewCatalogAction;
	private CreateNewFileAction createNewFileAction;
	private SendLocalFilesAction sendLocalFileAction;
	private DownloadRemoteFilesAction downloadRemoteFilesAction;
	private CopyAction copyAction;
	private PasteAction pasteAction;
	private FindAction findAction;
	private ChangePermissionsAction changePermissionsAction;
	
	// Navi bar actions
	private CloseNaviBarAction closeNaviBarAction;
	private NextSearchResultAction nextSearchResultAction;
	private PrevSearchResultAction prevSearchResultAction;
	
	private OtherFileFilter otherFileFilter;
	private AccessDeniedFilter accessDeniedFilter;
	
	class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
		public String getColumnText(Object obj, int index) {
			return getText(obj);
		}
		public Image getColumnImage(Object obj, int index) {
			return getImage(obj);
		}
		public Image getImage(Object obj) {
			return PlatformUI.getWorkbench().
					getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT);
		}
	}

	/**
	 * The constructor.
	 */
	public StorageBrowserView() {
		super();
		StorageManagementActivator.getDefault().setStorageView(this);
	}

	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public void createPartControl(Composite parent) {
		treeViewer = new TreeViewer(parent);
		treeViewer.setContentProvider(new ContentProviderImplementation(treeViewer));
		treeViewer.setLabelProvider(new LabelProviderImplementation());
		treeViewer.setInput(getInitalInput());
		treeViewer.expandAll();
		
		makeActions();
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
	}
	
	public RootNode getInitalInput() {
		if (rootNode != null) {
			return rootNode;
		}
		rootNode = new RootNode();
		GridNode gridNode = new GridNode();
		gridNode.setParent(rootNode);
		rootNode.add(gridNode);
		if (doubleClickAction == null) {
			doubleClickAction = new DoubleClickAction(treeViewer);
		}
		for (Storage storage : StorageManagementActivator.getDefault().getStorageList()) {
			System.out.println(" " + storage.getUrl());
			addStorage(storage, true);
		}
		return rootNode;
	}
	
	public void addStorage(Storage storage, boolean refresh) {
		if (rootNode == null || rootNode.getChildren().size() == 0) {
			return;
		}
		GridNode gridNode = (GridNode) rootNode.getChildren().get(0);
		StorageNode storageNode = new StorageNode();
		storageNode.setStorage(storage);
		storageNode.setParent(gridNode);
		gridNode.add(storageNode);
		if (refresh) {
			doubleClickAction.run(storageNode, false);
		}
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new MenuListener(this));
		
		Menu menu = menuMgr.createContextMenu(treeViewer.getControl());
		treeViewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, treeViewer);
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(createSortSubmenu());
		manager.add(createFilterSubmenu());
	}

	public void fillContextMenu(IMenuManager manager) {
		manager.add(hideShowStoragesAction);
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		manager.add(renameAction);
	}
	
	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(hideShowStoragesAction);
	}

	private void makeActions() {
		if (doubleClickAction == null) {
			doubleClickAction = new DoubleClickAction(treeViewer);
		}
		hideShowStoragesAction = new HideShowStoragesAction(treeViewer);
		renameAction = new RenameAction(this);
		deleteAction = new DeleteAction(this);
		createNewCatalogAction = new CreateNewCatalogAction(this);
		createNewFileAction = new CreateNewFileAction(this);
		sendLocalFileAction = new SendLocalFilesAction(this);
		downloadRemoteFilesAction = new DownloadRemoteFilesAction(this);
		pasteAction = new PasteAction(this);
		copyAction = new CopyAction(this);
		findAction = new FindAction(this);
		changePermissionsAction = new ChangePermissionsAction(this);
	}

	private void hookDoubleClickAction() {
		treeViewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}
	
	private MenuManager createSortSubmenu() {
		MenuManager sorterMenuManager = new MenuManager("Sort by");
		Action sortByNameAction = new Action("name", IAction.AS_RADIO_BUTTON) {
			@Override
			public void run() {
				treeViewer.setSorter(new NameSorter());
			}
		};
		sorterMenuManager.add(sortByNameAction);
		
		Action sortByLastModAction = new Action("last modification", IAction.AS_RADIO_BUTTON) {
			@Override
			public void run() {
				treeViewer.setSorter(new LastModifiedSorter());
			}
		};
		sorterMenuManager.add(sortByLastModAction);
		return sorterMenuManager;
	}
	
	private MenuManager createFilterSubmenu() {
		MenuManager filterMenuManager = new MenuManager("Filters");
		
		accessDeniedFilter = new AccessDeniedFilter();
		otherFileFilter = new OtherFileFilter();
		
		Action filterAccessDeniedAction = new Action("filter access denied", IAction.AS_CHECK_BOX) {
			@Override
			public void run() {
				if (this.isChecked()) {
					treeViewer.addFilter(accessDeniedFilter);
				} else {
					treeViewer.removeFilter(accessDeniedFilter);
				}
			}
		};
		filterMenuManager.add(filterAccessDeniedAction);
		
		Action filterOtherFilesAction = new Action("filter other files", IAction.AS_CHECK_BOX) {
			@Override
			public void run() {
				if (this.isChecked()) {
					treeViewer.addFilter(otherFileFilter);
				} else {
					treeViewer.removeFilter(otherFileFilter);
				}
			}
		};
		filterMenuManager.add(filterOtherFilesAction);
		
		return filterMenuManager;
	}
	
	public void addNaviBarActions() {
		if (closeNaviBarAction == null) {
			closeNaviBarAction = new CloseNaviBarAction(this);
			nextSearchResultAction = new NextSearchResultAction(this);
			prevSearchResultAction = new PrevSearchResultAction(this);
		}
		
		IToolBarManager manager = getViewSite().getActionBars().getToolBarManager();
		manager.removeAll();
		manager.add(prevSearchResultAction);
		manager.add(nextSearchResultAction);
		manager.add(closeNaviBarAction);
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		
		fillLocalToolBar(manager);
		manager.update(true);
	}
	
	public void removeNaviBarActions() {
		IToolBarManager manager = getViewSite().getActionBars().getToolBarManager();
		manager.removeAll();
		fillLocalToolBar(manager);
		manager.update(true);
	}
	
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		treeViewer.getControl().setFocus();
	}
	
	public TreeViewer getTreeViewer() {
		return treeViewer;
	}

	public HideShowStoragesAction getHideShowStoragesAction() {
		return hideShowStoragesAction;
	}

	public RenameAction getRenameAction() {
		return renameAction;
	}
	
	public DeleteAction getDeleteAction() {
		return deleteAction;
	}
	
	public CreateNewCatalogAction getCreateNewCatalogAction() {
		return createNewCatalogAction;
	}

	public DoubleClickAction getDoubleClickAction() {
		return doubleClickAction;
	}
	
	public CreateNewFileAction getCreateNewFileAction() {
		return createNewFileAction;
	}
	
	public SendLocalFilesAction getSendLocalFileAction() {
		return sendLocalFileAction;
	}
	
	public DownloadRemoteFilesAction getdDownloadRemoteFilesAction(){
		return downloadRemoteFilesAction;
	}

	public CopyAction getCopyAction() {
		return copyAction;
	}

	public void setCopyAction(CopyAction copyAction) {
		this.copyAction = copyAction;
	}

	public PasteAction getPasteAction() {
		return pasteAction;
	}

	public void setPasteAction(PasteAction pasteAction) {
		this.pasteAction = pasteAction;
	}

	public void setClipboard(IStructuredSelection selection) {
		this.clipboard = selection;
	}
	
	public IStructuredSelection getClipboard() {
		return clipboard;
	}

	public FindAction getFindAction() {
  	return findAction;
  }

	public void setFindAction(FindAction findAction) {
  	this.findAction = findAction;
  }

	public void setSearchResultIterator(ListIterator<FindAction.SearchResult> itr) {
	  nextSearchResultAction.setIterator(itr);
	  prevSearchResultAction.setIterator(itr);
  }

	public NextSearchResultAction getNextSearchResultAction() {
  	return nextSearchResultAction;
  }

	public PrevSearchResultAction getPrevSearchResultAction() {
  	return prevSearchResultAction;
  }

	public ChangePermissionsAction getChangePermissionsAction() {
  	return changePermissionsAction;
  }

	public void setChangePermissionsAction(
      ChangePermissionsAction changePermissionsAction) {
  	this.changePermissionsAction = changePermissionsAction;
  }
	
}